#! /usr/bin/env python
# ididdomodel.py
'''
This Module containes the Model Tier of the todo application.

getConnection  -  global method to retrieve the connection
TodoItemModel  -  Model class of the todo item
TodoItemDB     -  The DB class for the todo item
'''

import imp

try:
    imp.find_module('pymongo')
except ImportError:
    print('Please install the pymongo module.')

from pymongo import Connection
from pymongo.errors import PyMongoError
from pymongo.son_manipulator import AutoReference, NamespaceInjector

__author__ = "Tiago Seixas"
__copyright__ = "Copyright 2011, Tiago Seixas"
__credits__ = ["Tiago Seixas"]
__license__ = "GPL"
__version__ = "3"
__maintainer__ = "Tiago Seixas"
__email__ = "tiagoafseixas@gmail.com"
__status__ = "Prototype"

DATABASE_NAME = 'todo'

def get_connection():
    '''
    Returns a connection to the database
    TODO: user e login???
    '''
    try:
        conn = Connection()
    except ConnectionFailure as e:
        print(e)
        
    db = conn[DATABASE_NAME]
    db.add_son_manipulator(NamespaceInjector())
    db.add_son_manipulator(AutoReference(db))
    return db

class TodoItemModel:
    '''
    A representation of the TodoItem
    '''

    DEFAULT_PRIORITY = 5
    def __init__(self, item):
        self.title = item['title']
        self.created = item['created']
        self.done = False

        if 'ref_id' in item:
            self.ref_id = item['ref_id']
        else:
            self.ref_id = None
            
        if 'when' in item:
            self.when = item['when']
        else:
            self.when = None
            
        if 'priority' in item:
            self.priority = item['priority']
        else:
            self.priority = -1
            
        if 'where' in item:
            self.where = item['where']
        else:
            self.where = None

        if 'project' in item:
            self.project = item['project']
        else:
            self.project = None
 
    def get_effective_priority(self):
        if self.priority < 0:
            return self.DEFAULT_PRIORITY
        else:
            return self.priority

    def to_dict(self):
        '''
        Converts an object of type TodoItemModel to a dictionary

        Paramters:
          todoModel - the TodoItemModel instance

        Returns: Dictionary
        '''
        item = {
            'title' : self.title,
            'created' : self.created,
            'priority' : self.priority,
            'done' : self.done
            }
        if self.where is not None:
            item['where'] = self.where
        if self.project is not None:
            item['project'] = self.project
        if self.when is not None:
            item['when'] = self.when

        return item

class TodoItemDB:
    '''
    Interacts with the items collection in the database
    '''
    def __init__(self):
        self.db = get_connection()

    def insert(self, todo_item):
        '''
        Inserts a new item document in the database

        Parameters:
          todo_item - The TodoItemModel that is to be inserted

        Returns:
          void
        '''
        item = todo_item.to_dict()

        objs = self.db.items.find().sort('ref_id',-1).limit(1)

        if objs.count() > 0:
            for obj in objs:
                item['ref_id'] = int(obj['ref_id'] + 1)
        else:
            item['ref_id'] = 0

        try:
            self.db.items.insert(item)
        except PyMongoError as e:
            print(e)
            print('> Error inserting in DB.')

    def remove(self, ref_id):
        '''
        Removes an item using the object id.

        Parameters:
          ref_id_id - The ref_id of the item

        Returns:
          void
        '''
        try:
            self.db.items.remove({'ref_id' : ref_id})
        except PyMongoError as e:
            print(e)
            raise Exception('> Could not perform the removal operation')
            
    def find_all(self):
        '''
        Finds all todo items for a user

        Returns:
          a list of TodoItemModels
        '''
        try:
            aItems = self.db.items.find()
        except PyMongoError as e:
            print(e)
            print('> Error fetching items from db.')

        return_list = [];
        if aItems is not None:
            for item in aItems:
                return_list.append(TodoItemModel(item))

        return return_list

    def find(self, search_criteria):
        '''
        Finds all todo items for a user

        Returns:
          a list of TodoItemModels
        '''
        try:
            aItems = self.db.items.find(search_criteria)
        except PyMongoError as e:
            print(e)
            print('> Error fetching items from db.')

        return_list = [];
        if aItems is not None:
            for item in aItems:
                return_list.append(TodoItemModel(item))

        return return_list

    def update(self, ref_id, item):
        try:
            self.db.items.update(
                {'ref_id' : ref_id},
                { '$set' : item})
        except PyMongoError as e:
            print(e)
            print('> Error fetching items from db.')
